package org.jeecg.modules.mes.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.api.client.util.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.NumberUtils;
import org.jeecg.modules.mes.chiefdata.entity.MesChiefdataBom;
import org.jeecg.modules.mes.chiefdata.entity.MesChiefdataBomitem;
import org.jeecg.modules.mes.client.BomClient;
import org.jeecg.modules.mes.client.ProduceClient;
import org.jeecg.modules.mes.client.StockClient;
import org.jeecg.modules.mes.client.SystemClient;
import org.jeecg.modules.mes.order.entity.MesOrderProduce;
import org.jeecg.modules.mes.order.entity.MesOrderSale;
import org.jeecg.modules.mes.order.entity.MesProduceItem;
import org.jeecg.modules.mes.order.entity.MesSaleItem;
import org.jeecg.modules.mes.order.mapper.MesOrderProduceMapper;
import org.jeecg.modules.mes.order.mapper.MesProduceItemMapper;
import org.jeecg.modules.mes.order.mapper.MesProduceProcessMapper;
import org.jeecg.modules.mes.order.service.IMesOrderProduceService;
import org.jeecg.modules.mes.order.service.IMesOrderSaleService;
import org.jeecg.modules.mes.order.service.IMesProduceItemService;
import org.jeecg.modules.mes.order.service.IMesSaleItemService;
import org.jeecg.modules.mes.produce.entity.MesCommandbillInfo;
import org.jeecg.modules.mes.storage.entity.MesLackMaterial;
import org.jeecg.modules.mes.storage.entity.MesMaterielOccupy;
import org.jeecg.modules.mes.storage.entity.MesStockManage;
import org.jeecg.modules.system.entity.SysUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * @Description: 订单管理—生产订单
 * @Author: jeecg-boot
 * @Date: 2020-10-19
 * @Version: V1.0
 */
@Service
public class MesOrderProduceServiceImpl extends ServiceImpl<MesOrderProduceMapper, MesOrderProduce> implements IMesOrderProduceService {

    @Autowired
    private MesOrderProduceMapper mesOrderProduceMapper;
    @Autowired
    private MesProduceItemMapper mesProduceItemMapper;
    @Autowired
    private MesProduceProcessMapper mesProduceProcessMapper;
    @Autowired
    private IMesProduceItemService mesProduceItemService;
    @Autowired
    private IMesSaleItemService mesSaleItemService;
    @Autowired
    private IMesOrderSaleService mesOrderSaleService;
    @Autowired
    private BomClient bomClient;
    @Autowired
    private StockClient stockClient;
    @Autowired
    private SystemClient systemClient;
    @Autowired
    private ProduceClient produceClient;

    @Override
    @Transactional
    public void delMain(String id) {
        mesProduceItemMapper.deleteByMainId(id);
        mesProduceProcessMapper.deleteByMainId(id);
        mesOrderProduceMapper.deleteById(id);
    }

    @Override
    @Transactional
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            mesProduceItemMapper.deleteByMainId(id.toString());
            mesProduceProcessMapper.deleteByMainId(id.toString());
            mesOrderProduceMapper.deleteById(id);
        }
    }

    /**
     * 新增
     *
     * @param mesOrderProduce
     * @return
     */
    @Override
    @Transactional
    public boolean add(MesOrderProduce mesOrderProduce) {
        // 获取登录用户信息
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        String client = mesOrderProduce.getClient();
        QueryWrapper<MesOrderProduce> produceWrapperS = new QueryWrapper<>();
        produceWrapperS.eq("order_code", mesOrderProduce.getOrderCode());
        List<MesOrderProduce> produceOrdersS = this.list(produceWrapperS);
        if (produceOrdersS.size() > 0) {
            throw new RuntimeException("订单编号以存在！");
        }

        // 如果销售订单不为空，则生产订单与销售进行关联。反之，用户可以自主选择想要生产的产品
        if (StringUtils.isNotBlank(mesOrderProduce.getSaleorderCode())) {
            System.err.println(mesOrderProduce.getSaleorderCode());
            //销售订单不为空的情况下，判断该销售订单是否有生产订单
            QueryWrapper<MesOrderProduce> produceWrapper = new QueryWrapper<>();
            produceWrapper.eq("saleorder_code", mesOrderProduce.getSaleorderCode());
            List<MesOrderProduce> produceOrders = this.list(produceWrapper);
            Long grossAccount = 0L;//总的已生产数量
            Long sgAccount = 0L;//剩余可生产数量
            if (produceOrders.size() != 0) {
                for (MesOrderProduce orderProduce : produceOrders) {
                    grossAccount += Long.parseLong(orderProduce.getGrossAccount());//总数量
                }
                //查询出该销售订单的子表信息
                QueryWrapper<MesSaleItem> saleWrapper = new QueryWrapper<>();
                saleWrapper.eq("saleorder_id", mesOrderProduce.getSaleorderId());
                MesSaleItem messaleitem = mesSaleItemService.getOne(saleWrapper);
                //判断生产数量是否小于销售数量
                if (grossAccount > Long.parseLong(messaleitem.getOrderNum())) {
                    throw new RuntimeException("该销售订单没有可生产的数量了！请检查！");
                } else {
                    //大于的话，还可以生产剩余数量的销售订单
                    // System.out.println("getOrderNum:"+messaleitem.getOrderNum());
                    sgAccount = Long.parseLong(messaleitem.getOrderNum()) - grossAccount;
                    //System.out.println("sgAccount:"+sgAccount);
                }
            } else {
                //查询出该销售订单的子表信息
                QueryWrapper<MesSaleItem> saleWrapper = new QueryWrapper<>();
                saleWrapper.eq("saleorder_id", mesOrderProduce.getSaleorderId());
                MesSaleItem messaleitem = mesSaleItemService.getOne(saleWrapper);

                //不相等的话，还可以生产剩余数量的销售订单
                //System.out.println("getOrderNum:"+messaleitem.getOrderNum());
                sgAccount = Long.parseLong(messaleitem.getOrderNum()) - grossAccount;
                //System.out.println("sgAccount:"+sgAccount);
            }

            System.err.println(mesOrderProduce);
            String saleorderId = mesOrderProduce.getSaleorderId();
            System.err.println(saleorderId);
            System.out.println(sgAccount);
            //判断生产订单总数量必须要大于等于剩余可生产数量
            if (StringUtils.isNotBlank(mesOrderProduce.getGrossAccount()) && Long.parseLong(mesOrderProduce.getGrossAccount()) > sgAccount) {
                throw new RuntimeException("该销售订单剩余需生产的数量不足！请检查！");
            }

            if (StringUtils.isNotBlank(saleorderId)) {
                QueryWrapper<MesSaleItem> wrapper = new QueryWrapper<>();
                wrapper.eq("saleorder_id", saleorderId);
                List<MesSaleItem> saleItemList = mesSaleItemService.list(wrapper);
                MesOrderSale sale = mesOrderSaleService.getById(saleorderId);
                for (MesSaleItem saleItem : saleItemList) {
                    String mCode = saleItem.getMaterielCode();//物料编号
                    String mName = saleItem.getMaterielName();//物料名称
                    mesOrderProduce.setId(null);
                    mesOrderProduce.setCreateBy(sysUser.getUsername());
                    mesOrderProduce.setCreateTime(DateUtils.getDate());
                    mesOrderProduce.setMaterielId(saleItem.getMaterielId());//物料id
                    mesOrderProduce.setMaterielCode(mCode);
                    mesOrderProduce.setMaterielName(mName);
                    mesOrderProduce.setClient(sale.getSaleName());//客户
                    mesOrderProduce.setGauge(saleItem.getMaterielGauge());//物料规格
                    mesOrderProduce.setFactoryId(saleItem.getFactoryId());//工厂id
                    mesOrderProduce.setFactoryCode(saleItem.getFactoryCode());//工厂编号
                    mesOrderProduce.setFactoryName(saleItem.getFactoryName());//工厂名称
                    mesOrderProduce.setStorageSite(saleItem.getStorageSite());//库存地点
                    if (StringUtils.isNotBlank(mesOrderProduce.getGrossAccount())) {//如果生产总数量不为空的话，根据生产数量来
                        mesOrderProduce.setGrossAccount(mesOrderProduce.getGrossAccount());//生产总数量
                    } else {
                        mesOrderProduce.setGrossAccount(saleItem.getOrderNum());//订单数量
                    }
                    mesOrderProduce.setInputNum("0");//入库数量
                    mesOrderProduce.setRemainNum("0");//剩余数量
                    mesOrderProduce.setUnit(saleItem.getUnit());//单位
//					mesOrderProduce.setState("库存充足");
                    this.save(mesOrderProduce);
                    //通过物料编号，获取BOM主表id
                    MesChiefdataBom bom = bomClient.queryByMcode(mCode);
                    String bomId = bom.getId();
                    //通过BOM主表id，获取BOM子表数据（温馨提示：Bom主表为成品，Bom子表为组成成品所需的成分）
                    List<MesChiefdataBomitem> bomitems = bomClient.queryByMcodeZu(mCode);
                    String orderId = mesOrderProduce.getId();//生产订单主表id
                    if (bomitems.size() == 0) {
                        this.delMain(mesOrderProduce.getId());
                        throw new RuntimeException("找不到料号为 " + mCode + "的" + mName + " 对应的BOM数据！请检查！");
                    } else {
                        //半成品的概念 需要根据类型为BCP的类型去获取半成品物料信息
                        List<MesChiefdataBomitem> bcplist = new ArrayList<MesChiefdataBomitem>();
                        //所有半成品物料
                        List<MesChiefdataBomitem> mesChiefdataBomitems = bomClient.queryMesBomitemBCPMainId(bomId);
                        for (MesChiefdataBomitem bomitem : mesChiefdataBomitems) {
                            //通过BOM主表id，获取BOM子表数据（温馨提示：Bom主表为成品，Bom子表为组成成品所需的成分）
                            List<MesChiefdataBomitem> bomitems1 = bomClient.queryByMcodeZu(mCode);
                            if (bomitems1.size() > 0) {
                                //半成品的bom  需要拆解到这个生产订单bom下
                                System.out.println("bcpbomitem:" + bomitem);
                                bomitems1.forEach(System.out::println);
                                bcplist.addAll(bomitems1);
                            }
                        }
                        bomitems.addAll(bcplist);

                        for (MesChiefdataBomitem bomitem : bomitems) {
                            System.out.println(" item =" + bomitem);
                            //用量为0的是替代料，不用生成物料数据
                            if ("0".equals(bomitem.getQuantity())){
                                continue;
                            }
                            //生产订单子表数据，从bom表获取\
                            String bomItemcode = bomitem.getMaterielCode();//物料编号
                            String bomItemName = bomitem.getMaterielName();//物料名称
                            MesProduceItem produceItem = new MesProduceItem();
                            BeanUtils.copyProperties(bomitem, produceItem);
                            produceItem.setId(null);//主键设置为null
                            produceItem.setCreateBy(sysUser.getUsername());//创建人
                            produceItem.setCreateTime(DateUtils.getDate());//创建时间
                            produceItem.setProorderId(orderId);//生产订单主表id
                            produceItem.setCountUnit(bomitem.getUnit());//单位
                            produceItem.setIfDelivery("未发料");//发料状态
                            produceItem.setUnglazeNum("0");//未上料数量

                            bomitem.setQuantity(NumberUtils.getNumber_charAt(bomitem.getQuantity()));
                            //通过损耗率，计算得出该生产订单，每条bom所需的数量：（订单数量*用量）/ 1-损坏率
                            String wastageRate = bomitem.getWastageRate();
                            if (StringUtils.isNotBlank(wastageRate)) {
                                //有形损耗率等于0时，需求数量=用量*订单数
                                if (wastageRate.equals("0")) {
                                    BigDecimal quantity = new BigDecimal(bomitem.getQuantity());//用量
                                    BigDecimal totalNum = new BigDecimal(mesOrderProduce.getGrossAccount());//生产订单总数
                                    BigDecimal requireNum = quantity.multiply(totalNum);//需求数量=用量 * 生产订单总数量
                                    System.err.println(requireNum);
                                    produceItem.setRequireNum(requireNum.toString());//需求数量
                                    produceItem.setDeliveryNum("0");//已发料数量
                                } else {
                                    //有形损耗率不为0时，需求数量=用量*订单数/(1-损耗率)
                                    String[] split = wastageRate.split("%");//将损耗率的%分离
                                    float wastage = Float.parseFloat(split[0]);
                                    float fnum = Float.parseFloat(divide(wastage, 100));//将损耗率转变为小数
                                    System.err.println(fnum);
                                    float requireNum = Float.parseFloat(bomitem.getQuantity()) * Float.parseFloat(mesOrderProduce.getGrossAccount());
                                    System.err.println(requireNum);
                                    System.err.println(divide(requireNum, 1 - fnum));
                                    produceItem.setRequireNum(divide(requireNum, 1 - fnum));//需求数量
//									produceItem.setUndeliveryNum(divide(requireNum, 1 - fnum));//未发料数量
                                    produceItem.setDeliveryNum("0");//已发料数量
                                }
                            }
                            //半成品不判断库存
                            if ("bcp".equals(bomitem.getMaterialType() == null ? "" : bomitem.getMaterialType().toLowerCase())) {
                                mesProduceItemService.save(produceItem);
                                continue;
                            }
                            //根据物料料号，获取库存数据
                            //MesStockManage mesStockManage = stockClient.queryByMcode(bomItemcode);//注释原因：逻辑修改为根据客户查询该客户的区域位下是否存在该物料
                            MesStockManage mesStockManage = stockClient.queryByMcodeAndClient(bomItemcode, client);
                            if (mesStockManage != null) {
                                //若库存数量不为空，则添加生产订单子表数据
                                produceItem.setFactoryId(mesStockManage.getFactoryId());//工厂id
                                produceItem.setFactoryCode(mesStockManage.getFactoryCode());//工厂编号
                                produceItem.setFactoryName(mesStockManage.getFactoryName());//工厂名称
                                produceItem.setStorageSite(mesStockManage.getStoreName());//库存地点
                                produceItem.setStockNum(mesStockManage.getStockNum());//库存数量
                                mesProduceItemService.save(produceItem);
                            } else {
                                produceItem.setStockNum("0");//库存数量
                                mesProduceItemService.save(produceItem);
                            }

                            //缺料判断：库存数量 - 需求数量是否为0
                            BigDecimal stockNum = new BigDecimal(produceItem.getStockNum());//库存数量
                            if (StringUtils.isBlank(produceItem.getRequireNum())) {
                                produceItem.setRequireNum("0");
                            }
                            BigDecimal requireNum = new BigDecimal(produceItem.getRequireNum());//需求数量
                            BigDecimal remainNum = stockNum.subtract(requireNum);//剩余数量=库存数量-需求数量
//								if (stockNum - requireNum < 0) {
                            if (remainNum.compareTo(BigDecimal.ZERO) == -1) {
                                mesOrderProduce.setState("缺料");
                                this.updateById(mesOrderProduce);
                                // 若物料不足，则添加缺料清单
                                BigDecimal lackNum = remainNum.abs();//缺料数量 = 库存数量 - 需求数量
                                System.err.println(lackNum);
                                MesLackMaterial mesLackMaterial = new MesLackMaterial();
                                BeanUtils.copyProperties(bomitem, mesLackMaterial);
                                mesLackMaterial.setId(null);//主键设置为null
                                mesLackMaterial.setCreateBy(sysUser.getUsername());//创建人
                                mesLackMaterial.setCreateTime(DateUtils.getDate());//创建时间
                                mesLackMaterial.setOrderId(mesOrderProduce.getId());// 生产订单id
                                mesLackMaterial.setProduceItemid(produceItem.getId());// 生产订单子表id
                                mesLackMaterial.setOrderCode(mesOrderProduce.getOrderCode());//生产订单编号
                                mesLackMaterial.setOrderName(mesOrderProduce.getOrderName());//生产订单名称
                                mesLackMaterial.setMaterielGague(bomitem.getMaterielGauge());//物料规格
                                mesLackMaterial.setLackNum(lackNum.toString());//缺料数量
                                mesLackMaterial.setStockNum(stockNum.toString());//库存数量
                                mesLackMaterial.setUnit(bomitem.getUnit());//单位
                                BigDecimal needNum = lackNum.add(stockNum);
                                mesLackMaterial.setRequireNum(needNum.toString());//库存所需达到的数量
                                stockClient.addLack(mesLackMaterial);

                                //缺料，发送提醒
                                List<SysUser> sysUserList = systemClient.queryRoleByCode("repository");
                                if (sysUserList != null && sysUserList.size() > 0) {
                                    for (SysUser user : sysUserList) {
                                        //缺料，添加提醒
                                        systemClient.sendRemindMessage(user.getUsername(), "物料不足"
                                                , produceItem.getMaterielName() + "数量不足，" + "料号:" + produceItem.getMaterielCode() + "，规格：" + produceItem.getMaterielGauge());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else {
            if (StringUtils.isBlank(mesOrderProduce.getGrossAccount())
                    || StringUtils.isBlank(mesOrderProduce.getMaterielCode())) {
                throw new RuntimeException("自产时，物料编号和订单总数量不能为空！请检查！");
            }
            mesOrderProduce.setInputNum("0");//入库数量
            mesOrderProduce.setRemainNum("0");//剩余数量
            this.save(mesOrderProduce);
            if (StringUtils.isNotBlank(mesOrderProduce.getMaterielCode())) {
                String mCode = mesOrderProduce.getMaterielCode();//成品料号
                String mName = mesOrderProduce.getMaterielName();//成品名称
                //通过成品，获取BOM主表id
                MesChiefdataBom bom = bomClient.queryByMcode(mCode);
                if (bom == null) {
                    throw new RuntimeException("成品料号有误，请检查！");
                }
                String bomId = bom.getId();
                //通过BOM主表id，获取BOM子表数据（温馨提示：Bom主表为成品，Bom子表为组成成品所需的成分）
                List<MesChiefdataBomitem> bomitems = bomClient.queryMesBomitemByMainId(bomId);
                ;
                System.err.println("bom.size==============================" + bomitems.size());
                String orderId = mesOrderProduce.getId();//生产订单主表id
                if (bomitems.size() == 0) {
                    throw new RuntimeException("找不到料号为 " + mCode + "的" + mName + " 对应的BOM数据！请检查！");
                } else {
                    List<MesChiefdataBomitem> bcplist = new ArrayList<MesChiefdataBomitem>();
					/*for(MesChiefdataBomitem bomitem : bomitems){
						MesChiefdataBom bom1 = bomClient.queryByMcode(bomitem.getMaterielCode());
						if(bom1 != null&&bom1.getId()!=null){
							//半成品的bom  需要拆解到这个生产订单bom下
							bomitem.setMaterielGrade(bom1.getQuery2());
							bomitem.setPackup("bcp");
							List<MesChiefdataBomitem> bomitems1 = bomClient.queryMesBomitemByMainId(bom1.getId());
							for(MesChiefdataBomitem item1 : bomitems1){
								item1.setMaterielGrade(bom1.getQuery2());
							}
							bcplist.addAll(bomitems1);
						}else{
							bomitem.setMaterielGrade(bom.getQuery2());
						}
					}
					bomitems.addAll(bcplist);*/
                    //所有半成品物料 需要拆解到这个生产订单bom下
                    List<MesChiefdataBomitem> mesChiefdataBomitems = bomClient.queryMesBomitemBCPMainId(bomId);
                    for (MesChiefdataBomitem bomitem : mesChiefdataBomitems) {
                        //通过BOM主表id，获取BOM子表数据（温馨提示：Bom主表为成品，Bom子表为组成成品所需的成分）
                        List<MesChiefdataBomitem> bomitems1 = bomClient.queryByMcodeZu(mCode);
                        if (bomitems1.size() > 0) {
                            //半成品的bom  需要拆解到这个生产订单bom下
                            System.out.println("bcpbomitem:" + bomitem);
                            bomitems1.forEach(System.out::println);
                            bcplist.addAll(bomitems1);
                        }
                    }
                    bomitems.addAll(bcplist);
                    //在循环之前根据bom料号 取物料数据map信息

                    for (MesChiefdataBomitem bomitem : bomitems) {
                        System.out.println(" item :1" + bomitem);
                        //用量为0的是替代料，不用生成物料数据
                        if ("0".equals(bomitem.getQuantity())){
                            continue;
                        }
                        //生产订单子表数据，从bom表获取\
                        String bomItemcode = bomitem.getMaterielCode();//物料编号
                        String bomItemName = bomitem.getMaterielName();//物料名称
                        MesProduceItem produceItem = new MesProduceItem();
                        BeanUtils.copyProperties(bomitem, produceItem);
                        produceItem.setId(null);//主键设置
                        produceItem.setCreateBy(sysUser.getUsername());
                        produceItem.setCreateTime(DateUtils.getDate());
                        produceItem.setProorderId(orderId);//生产订单主表id
                        produceItem.setCountUnit(bomitem.getUnit());//单位
                        produceItem.setIfDelivery("未发料");//发料状态
                        produceItem.setUnglazeNum("0");//未上料数量

                        //通过损耗率，计算得出该生产订单，每条bom所需的数量：（订单数量*用量）/ 1-损坏率
                        String wastageRate = bomitem.getIntangibleRate();
                        if (StringUtils.isNotBlank(wastageRate)) {
                            if (wastageRate.equals("0")) {
                                BigDecimal quantity = new BigDecimal(bomitem.getQuantity());//用量
                                BigDecimal totalNum = new BigDecimal(mesOrderProduce.getGrossAccount());//生产订单总数
                                BigDecimal requireNum = quantity.multiply(totalNum);//bom需求总量=用量*生产订单总数
                                produceItem.setRequireNum(requireNum.toString());//需求数量
//								produceItem.setUndeliveryNum(requireNum+"");//未发料数量
                                produceItem.setDeliveryNum("0");//已发料数量
                            } else {
                                String[] split = wastageRate.split("%");
                                float wastage = Float.parseFloat(split[0]);
                                float fnum = Float.parseFloat(divide(wastage, 100));
                                System.err.println(fnum);
                                float requireNum = Float.parseFloat(bomitem.getQuantity()) * Float.parseFloat(mesOrderProduce.getGrossAccount());
                                System.err.println(requireNum);
                                System.err.println(divide(requireNum, 1 - fnum));
                                produceItem.setRequireNum(divideInteger(requireNum, 1 - fnum));//需求数量
//								produceItem.setUndeliveryNum(divide(requireNum, 1 - fnum));//未发料数量
                                produceItem.setDeliveryNum("0");//已发料数量
                            }
                        } else {
                            throw new RuntimeException("Bom的损耗率不能为空！请检查！");
                        }
                        //半成品不判断库存
                        if ("bcp".equals(bomitem.getMaterialType() == null ? "" : bomitem.getMaterialType().toLowerCase())) {
                            mesProduceItemService.save(produceItem);
                            continue;
                        }
                        //根据物料料号，获取库存数据
                        System.err.println("bom的料号+++++++++++++++++++++++" + bomItemcode);
                        //MesStockManage mesStockManage = stockClient.queryByMcode(bomItemcode);//注释原因：逻辑修改为根据客户查询该客户的区域位下是否存在该物料
                        MesStockManage mesStockManage = stockClient.queryByMcodeAndClient(bomItemcode, client);
                        if (mesStockManage == null||StringUtils.isBlank(produceItem.getStockNum())) {
//                            System.err.println("空的库存数据================" + mesStockManage);
//                            //如果物料的库存数据为空，则提醒用户添加库存数据
//                            this.delMain(mesOrderProduce.getId());
//                            throw new RuntimeException("找不到料号为 " + bomItemcode + "的" + bomItemName + " 对应的库存数据！请检查！");
                            produceItem.setStockNum("0");//库存数量
                            mesProduceItemService.save(produceItem);
                        } else {
                            //若库存数量不为空，则添加生产订单子表数据
                            produceItem.setFactoryId(mesStockManage.getFactoryId());//工厂id
                            produceItem.setFactoryCode(mesStockManage.getFactoryCode());//工厂编号
                            produceItem.setFactoryName(mesStockManage.getFactoryName());//工厂名称
                            produceItem.setStorageSite(mesStockManage.getStoreName());//库存地点
                            produceItem.setStockNum(mesStockManage.getStockNum());//库存数量
                            mesProduceItemService.save(produceItem);

                        }

                        //缺料判断：库存数量 - 需求数量是否为0
                        BigDecimal stockNum = new BigDecimal(produceItem.getStockNum());//库存数量
                        BigDecimal requireNum = new BigDecimal((produceItem.getRequireNum()));//需求数量
                        BigDecimal remainNum = stockNum.subtract(requireNum);//剩余数量 = 库存数量 - 需求数量
                        //如果剩余数量小于0，则代表缺料，添加缺料数据；反之则代表库存充足，删除缺料数据
                        if (remainNum.compareTo(BigDecimal.ZERO) == -1) {
                            mesOrderProduce.setState("缺料");
                            this.updateById(mesOrderProduce);
                            // 若物料不足，则添加缺料清单
                            BigDecimal lackNum = remainNum.abs();//缺料数量 = 库存数量 - 需求数量
                            System.err.println(lackNum);
                            MesLackMaterial mesLackMaterial = new MesLackMaterial();
                            BeanUtils.copyProperties(bomitem, mesLackMaterial);
                            mesLackMaterial.setId(null);//主键设置为null
                            mesLackMaterial.setCreateBy(null);//创建人设置为null
                            mesLackMaterial.setCreateTime(null);//创建时间设置为null
                            mesLackMaterial.setOrderId(mesOrderProduce.getId());// 生产订单id
                            mesLackMaterial.setProduceItemid(produceItem.getId());// 生产订单子表id
                            mesLackMaterial.setOrderCode(mesOrderProduce.getOrderCode());//生产订单编号
                            mesLackMaterial.setOrderName(mesOrderProduce.getOrderName());//生产订单名称
                            mesLackMaterial.setMaterielGague(bomitem.getMaterielGauge());//物料规格
                            mesLackMaterial.setLackNum(lackNum.toString());//缺料数量
                            mesLackMaterial.setStockNum(stockNum.toString());//库存数量
                            mesLackMaterial.setUnit(bomitem.getUnit());//单位
                            BigDecimal needNum = lackNum.add(stockNum);
                            mesLackMaterial.setRequireNum(needNum.toString());//库存所需达到的数量
                            stockClient.addLack(mesLackMaterial);
                            //缺料，发送提醒
                            List<SysUser> sysUserList = systemClient.queryRoleByCode("repository");
                            if (sysUserList != null && sysUserList.size() > 0) {
                                for (SysUser user : sysUserList) {
                                    //缺料，添加提醒
                                    systemClient.sendRemindMessage(user.getUsername(), "物料不足"
                                            , produceItem.getMaterielName() + "数量不足，" + "料号:" + produceItem.getMaterielCode() + "，规格：" + produceItem.getMaterielGauge() + ",数量：" + lackNum);
                                }
                            }
                        }
                    }
                }
            } else {
                throw new RuntimeException("物料料号不能为空！");
            }
        }
        //如果通过生产订单id，在缺料表里找不到数据，则改变该生产订单的状态为库存充足，反之则为缺料
        if (StringUtils.isNotBlank(mesOrderProduce.getId())) {
            List<MesLackMaterial> lackMaterialList = stockClient.queryByOrderId(mesOrderProduce.getId());
            if (lackMaterialList.size() == 0) {
//				mesOrderProduce.setState("库存充足");handGetMaterials
//				this.updateById(mesOrderProduce);
                QueryWrapper<MesProduceItem> wrapper = new QueryWrapper<>();
                wrapper.eq("proorder_id", mesOrderProduce.getId());
                List<MesProduceItem> produceItemList = mesProduceItemService.list(wrapper);
                for (MesProduceItem item : produceItemList) {
                    updateMaterielOccupy(item, mesOrderProduce);
                }
            } else {
                mesOrderProduce.setState("缺料");
                this.updateById(mesOrderProduce);
            }
        } else {
            throw new RuntimeException("生产订单ID不能为空！或销售订单没绑定bom");
        }
        return true;
    }


    //定义方法
    public static String divide(float a, float b) {
        //“0.00000”确定精度
        DecimalFormat dF = new DecimalFormat("0.00000");
        return dF.format((float) a / b);
    }

    //定义方法
    public static String divideInteger(float a, float b) {
        //“0”确定精度
        DecimalFormat dF = new DecimalFormat("0");
        return dF.format((float) a / b);
    }

    /**
     * 库存充足，进行物料领用
     *
     * @param produceItem     生产订单子表
     * @param mesOrderProduce 生产订单
     * @return
     */
    public boolean updateMaterielOccupy(MesProduceItem produceItem, MesOrderProduce mesOrderProduce) {
        String orderName = mesOrderProduce.getOrderName();//订单名称
        String mType = produceItem.getMaterielType();//物料类型
        String mName = produceItem.getMaterielName();//物料名称
        System.err.println("物料类型==========================================" + mType);
        //如果物料类型为辅料,则发送辅料回温提醒
        if (StringUtils.isNotBlank(mType) && mType.equals("PCB")) {
            // 获取登录用户信息
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            System.err.println(sysUser);
            //测试时，向当前登录用户发送消息提醒；正式上线后，需要向仓库人员（溢哲渝设定）发送辅料回温提醒
            bomClient.sendHeatMessage(sysUser.getUsername(), orderName, mName);
        }
        String mCode = produceItem.getMaterielCode();
        if (StringUtils.isBlank(produceItem.getRequireNum())) {
            produceItem.setRequireNum("0");
        }
        BigDecimal requireNum = new BigDecimal(produceItem.getRequireNum());
        MesMaterielOccupy mesMaterielOccupy = new MesMaterielOccupy();
        BeanUtils.copyProperties(produceItem, mesMaterielOccupy);
        mesMaterielOccupy.setId(null);//主键设置为null
        mesMaterielOccupy.setCreateBy(null);//创建人设置为null
        mesMaterielOccupy.setCreateTime(null);//创建时间设置为null
        mesMaterielOccupy.setMaterielGague(produceItem.getMaterielGauge());//物料规格
        mesMaterielOccupy.setOrderId(mesOrderProduce.getId());//生产订单id
        mesMaterielOccupy.setOrderCode(mesOrderProduce.getOrderCode());//生产订单编号
        mesMaterielOccupy.setOrderName(orderName);//生产订单名称
        mesMaterielOccupy.setOccupyNum(requireNum.toString());//需求数量
        mesMaterielOccupy.setUnusedNum(requireNum.toString());//未使用数量
        mesMaterielOccupy.setSendNum("0");//发料数量
        mesMaterielOccupy.setWithdrawNum("0");//退料数量
        mesMaterielOccupy.setTransformNum("0");//转产数量
        mesMaterielOccupy.setUnit(produceItem.getCountUnit());//单位
        mesMaterielOccupy.setOccupyPerson(produceItem.getCreateBy());//领用人
        mesMaterielOccupy.setOccupyTime(new Date());//领用时间
        //物料领用后，修改库存数量，通过料号、获取该物料的对应的库存数量
//        MesStockManage mesStockManage = stockClient.queryByMcode(mCode);
        MesStockManage mesStockManage = stockClient.queryByMcodeAndClient(mCode,mesOrderProduce.getClient());
        if (mesStockManage != null&&mesStockManage.getStockNum()!=null) {
            BigDecimal stockNum = new BigDecimal(mesStockManage.getStockNum()); //库存数量
            BigDecimal minimun = new BigDecimal(StringUtils.isBlank(mesStockManage.getMinimum()) ? "0" : mesStockManage.getMinimum());//库存临界点
            BigDecimal remaninNum = stockNum.subtract(requireNum);//剩余数量 = 库存数量-需求数量
            System.err.println(remaninNum);
            //若剩余数量小于0，删除领料单，并修改状态为缺料，同时添加缺料清单
            if (remaninNum.compareTo(BigDecimal.ZERO) > -1) {
                mesStockManage.setStockNum(remaninNum.toString());
                //不修改库存
                //stockClient.stockEdit(mesStockManage);
                //若剩余数量小于库存临界点，则提醒用户及时采购
                if (remaninNum.compareTo(minimun) < 1) {
                    // 获取登录用户信息
                    LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                    System.err.println(sysUser);
                    //测试时，向当前登录用户发送消息提醒；正式上线后，需要向采购人员（溢哲渝设定）发送库存临界点警告
                    bomClient.sendMessage(sysUser.getUsername(), mesStockManage.getMaterielName());
                }
                produceItem.setStockNum(stockNum.toString());//修改库存数量
                mesProduceItemService.updateById(produceItem);//更新操作
                mesOrderProduce.setState("待发料");
                this.updateById(mesOrderProduce);
            } else {
                BigDecimal lackNum = remaninNum.abs();//缺料数量 = 库存数量 - 需求数量
                // 若物料不足，则添加缺料清单
                MesLackMaterial mesLackMaterial = new MesLackMaterial();
                BeanUtils.copyProperties(produceItem, mesLackMaterial);
                mesLackMaterial.setId(null);//主键设置为null
                mesLackMaterial.setOrderId(mesOrderProduce.getId());// 生产订单id
                mesLackMaterial.setProduceItemid(produceItem.getId());// 生产订单子表id
                mesLackMaterial.setOrderCode(mesOrderProduce.getOrderCode());//生产订单编号
                mesLackMaterial.setOrderName(mesOrderProduce.getOrderName());//生产订单名称
                mesLackMaterial.setMaterielGague(produceItem.getMaterielGauge());//物料规格
                mesLackMaterial.setLackNum(lackNum.toString());//缺料数量
                mesLackMaterial.setStockNum(stockNum.toString());//库存数量
                mesLackMaterial.setUnit(produceItem.getCountUnit());//单位
                BigDecimal needNum = stockNum.add(remaninNum);
                mesLackMaterial.setRequireNum(needNum.toString());//库存所需达到的数量
                stockClient.addLack(mesLackMaterial);
                mesOrderProduce.setState("缺料");
                this.updateById(mesOrderProduce);
                //删除已添加的领料单
                stockClient.deleteOccupyByorderId(mesOrderProduce.getId());
                return false;
            }
        }
        stockClient.addOccupy(mesMaterielOccupy);
        return true;
    }

    /**
     * 生产订单-分页列表查询
     */
    @Override
    public Result<?> queryPageList(Page<MesOrderProduce> page, QueryWrapper<MesOrderProduce> queryWrapper) {
        IPage<MesOrderProduce> pageList = mesOrderProduceMapper.selectPage(page, queryWrapper);
        List<MesOrderProduce> mesOrderProduceList = pageList.getRecords();
        List<String> produceIds = Lists.newArrayList();
        for (MesOrderProduce mop : mesOrderProduceList) {
            produceIds.add(mop.getId());
        }
        if (com.epms.util.ObjectHelper.isNotEmpty(produceIds)) {
            List<MesCommandbillInfo> mesCommandBillInfoList = produceClient.queryMesCommandBillInfoByProduceId(produceIds);
            if (com.epms.util.ObjectHelper.isNotEmpty(mesCommandBillInfoList)) {
                for (MesOrderProduce mop : mesOrderProduceList) {
                    mop.setRemainNum(mop.getGrossAccount());
                    for (MesCommandbillInfo mcbi : mesCommandBillInfoList) {
                        if (mop.getId().equals(mcbi.getProduceId())) {
                            if ("SMT".equals(mcbi.getProduceGrade())) {
                                this.setMesOrderProduce(mop, mcbi.getUninputNum());
                                continue;
                            }
                            if ("DIP".equals(mcbi.getProduceGrade())) {
                                this.setMesOrderProduce(mop, mcbi.getUninputNum());
                                continue;
                            }
                            if ("ASSEMBLY".equals(mcbi.getProduceGrade())) {
                                this.setMesOrderProduce(mop, mcbi.getUninputNum());
                                continue;
                            }
                        }
                    }
                }
            }
        }
        return Result.ok(pageList);
    }

    /**
     * 如果有多个制令单，那么取未入库数量最小的那个制令单的未入库信息进行计算生产订单的入库数量
     */
    private void setMesOrderProduce(MesOrderProduce mop, String unInputNum) {
        if (new BigDecimal(unInputNum).compareTo(new BigDecimal(mop.getRemainNum())) == -1) {
            mop.setRemainNum(unInputNum);
            mop.setInputNum(new BigDecimal(mop.getGrossAccount()).subtract(new BigDecimal(unInputNum)).toString());//入库数
            if (mop.getGrossAccount().equals(mop.getInputNum())) {
                mop.setState("入库完成");
            }
        }
    }
}
